<template>
  <section>
    <!--工具条-->
    <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
      <el-form :inline="true" :model="filters">
        <el-form-item label="日志" prop="Log">
          <el-input ref="apilog" v-model="filters.Log" type="textarea" rows="10" cols="200" />
        </el-form-item>
        <el-form-item>
          <el-button size="small" type="primary" @click="formatApiLog">转换</el-button>
          <el-button size="small" type="primary" @click="pasteApiLog">粘贴并转换</el-button>
        </el-form-item>
      </el-form>
    </el-col>

    <!--列表-->
    <template>
      <el-table :data="datas" size="small" highlight-current-row style="width: 100%;">
        <el-table-column type="expand">
          <template slot-scope="scope">
            <el-form label-position="left" style="font-size: 0">
              <el-form-item
                v-for="(v, k, i) in {
                  '00_From': '来自哪个服务',
                  '04_ClientIp': '客户端 ID',
                  '05_ServerIp': '服务端 ID',
                  '06_TraceID': '请求 ID',
                  '07_SpanId': '调用次序',
                  '14_HostName': '主机名',
                  '15_LibVersion': '框架版本号',
                  '17_Version': '服务版本号',
                  '18_AppVersion': 'App 版本号',
                }"
                :key="i"
                :label="v"
              >
                <el-tooltip v-if="!!scope.row[k]" content="点击复制">
                  <el-link type="primary" icon="el-icon-copy-document" @click="copyPart(scope.row[k])">
                    {{ scope.row[k] }}
                  </el-link>
                </el-tooltip>
              </el-form-item>
            </el-form>
          </template>
        </el-table-column>
        <el-table-column
          v-for="(v, k, i) in {
            '01_Service': ['服务名', 300],
            '02_Method': ['方法名', 600],
            '09_UserID': ['用户 ID', 100],
            '10_RequestTime': ['请求开始时间', 200],
            '11_Code': ['接口返回码', 80, false],
            '12_Delay': ['接口延时', 80, false],
            '19_RoomID': ['房间 ID', 100],
          }"
          :key="i"
          :prop="k"
          :label="v[0]"
          :width="v[1]"
        >
          <template slot-scope="scope">
            <el-tooltip v-if="!!scope.row[k] && v.length === 2" content="点击复制">
              <el-link type="primary" icon="el-icon-copy-document" @click="copyPart(scope.row[k])">
                {{ scope.row[k] }}
              </el-link>
            </el-tooltip>
            {{ v.length === 3 && !v[2] ? scope.row[k] : '' }}
          </template>
        </el-table-column>
        <el-table-column label="操作" min-width="100" fixed="right">
          <template slot-scope="scope">
            <el-button size="mini" @click="showDetail(scope.row)">详情</el-button>
          </template>
        </el-table-column>
      </el-table>
      <el-col :span="24" class="toolbar">
        <el-pagination
          style="float:right;"
          layout="total, prev, pager, next"
          :current-page="page"
          :page-size="pageSize"
          :total="total"
          @current-change="handleCurrentChange"
        />
      </el-col>
    </template>

    <!--配置界面-->
    <el-dialog :close-on-click-modal="false" :modal="true" too="5vh" title="消息详情" :visible.sync="dataFormVisible" width="90%">
      <el-form ref="dataForm" :inline="true" :model="dataForm" size="mini">
        <el-row>
          <el-col :span="2">
            <el-form-item>
              <el-tooltip content="点击复制">
                <el-link type="primary" icon="el-icon-copy-document" @click="copyPart(dataForm['03_Header'])">
                  头部信息
                </el-link>
              </el-tooltip>
            </el-form-item>
          </el-col>
          <el-col :span="22">
            <el-form-item>
              <el-input v-model="dataForm['03_Header']" type="textarea" rows="10" cols="220" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="2">
            <el-form-item>
              <el-tooltip content="点击复制">
                <el-link type="primary" icon="el-icon-copy-document" @click="copyPart(dataForm['08_Param'])">
                  请求参数
                </el-link>
              </el-tooltip>
            </el-form-item>
          </el-col>
          <el-col :span="22">
            <el-form-item>
              <el-input v-model="dataForm['08_Param']" type="textarea" rows="10" cols="220" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="2">
            <el-form-item>
              <el-tooltip content="点击复制">
                <el-link type="primary" icon="el-icon-copy-document" @click="copyPart(dataForm['13_Response'])">
                  响应信息
                </el-link>
              </el-tooltip>
            </el-form-item>
          </el-col>
          <el-col :span="22">
            <el-form-item>
              <el-input v-model="dataForm['13_Response']" type="textarea" rows="10" cols="220" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="2">
            <el-form-item>
              <el-tooltip content="点击复制">
                <el-link type="primary" icon="el-icon-copy-document" @click="copyPart(dataForm['16_IO'])">
                  IO 操作:
                </el-link>
              </el-tooltip>
            </el-form-item>
          </el-col>
          <el-col :span="22">
            <el-form-item>
              <el-input v-model="dataForm['16_IO']" type="textarea" rows="1" cols="220" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <template>
            <el-table :data="iodatas" size="small" highlight-current-row stripe style="width: 100%;">
              <el-table-column prop="time" label="时间" width="160" />
              <el-table-column prop="logtype" label="日志类型" width="100">
                <template slot-scope="scope">
                  <el-tag
                    :type="scope.row.logtype === '[Debug]' ? 'info' :
                      scope.row.logtype === '[Info]' ? 'warning' :
                      ['[Warn]', '[Error]'].includes(scope.row.logtype) ? 'danger' : 'primary'"
                  >
                    {{ scope.row.logtype }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column prop="span" label="执行耗时(ms)" width="100" />
              <el-table-column prop="codepos" label="代码位置" min-width="400">
                <template slot-scope="scope">
                  <el-tooltip v-for="(line, line_id) in scope.row.codepos.split('\n')" :key="line_id" content="点击复制">
                    <div>
                      <el-link type="primary" icon="el-icon-copy-document" @click="copyPart(line)">
                        {{ line }}
                      </el-link>
                    </div>
                  </el-tooltip>
                </template>
              </el-table-column>
              <el-table-column prop="msg" label="消息" width="1000">
                <template slot-scope="scope">
                  <el-tooltip content="点击复制">
                    <el-link type="danger" icon="el-icon-copy-document" @click="copyPart(scope.row.msg)">
                      {{ scope.row.msg }}
                    </el-link>
                  </el-tooltip>
                </template>
              </el-table-column>
            </el-table>
          </template>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="detailClose()">关闭</el-button>
      </div>
    </el-dialog>

  </section>
</template>

<script>
export default {
  data() {
    return {
      total: 0,

      page: 1,

      pageSize: 10,

      dataFormVisible: false,

      filters: {
        Log: null
      },
      dataForm: {

      },

      datas: null,
      iodatas: null,
      all: null
    }
  },
  methods: {
    handleCurrentChange(val) {
      val = val ? +val : 1
      this.datas = []
      for (let i = (val - 1) * this.pageSize; i < val * this.pageSize && i < this.all.length; i++) {
        this.datas.push(this.all[i])
      }
    },
    formatApiLog() {
      // console.log(this.filters.Log)

      this.all = []
      this.datas = []
      this.total = 0
      for (const line of this.filters.Log.split('\n')) {
        let j
        try {
          j = JSON.parse(line)
        } catch (e) {
          this.$message.error(e)
          return
        }

        this.all.push(j)
      }

      this.total = this.all.length
      this.handleCurrentChange(1)
    },
    pasteApiLog() {
      navigator.clipboard.readText().then((txt) => {
        // console.log(txt)

        this.filters.Log = txt
        this.all = []
        this.datas = []
        this.total = 0
        for (const line of txt.split('\n')) {
          let j
          try {
            j = JSON.parse(line)
          } catch (e) {
            this.$message.error(e)
            return
          }

          this.all.push(j)
        }

        this.total = this.all.length
        this.handleCurrentChange(1)
      })
    },
    showDetail(row) {
      this.dataFormVisible = true
      try {
        this.dataForm['03_Header'] = JSON.stringify(JSON.parse(row['03_Header']), null, 4)
      } catch (e) {
        this.dataForm['03_Header'] = row['03_Header'] && row['03_Header'].replaceAll('{', '{\n\t').replaceAll('"}', '"\n}').replaceAll('","', '",\n\t"')
      }
      try {
        this.dataForm['08_Param'] = JSON.stringify(JSON.parse(row['08_Param']), null, 4)
      } catch (e) {
        this.dataForm['08_Param'] = row['08_Param'] && row['08_Param'].replaceAll('{', '{\n\t').replaceAll('"}', '"\n}').replaceAll('","', '",\n\t"')
      }
      try {
        this.dataForm['13_Response'] = JSON.stringify(JSON.parse(row['13_Response']), null, 4)
      } catch (e) {
        this.dataForm['13_Response'] = row['13_Response'] && row['13_Response'].replaceAll('{', '{\n\t').replaceAll('"}', '"\n}').replaceAll('","', '",\n\t"')
      }
      this.dataForm['16_IO'] = row['16_IO']

      this.iodatas = []
      this.paramdatas = []

      if (row['16_IO']) {
        const lines = row['16_IO'].split('\n')
        if (lines.length === 1 && lines[0] === 'len: 0') {
          return
        }

        const time_pre = row['10_RequestTime'].substring(0, 14)
        for (let i = 0; i < lines.length;) {
          const line = lines[i]
          if (line === '' || line.startsWith('len: ')) {
            i++
            continue
          }

          const parts1 = line.split(' ')
          let time = ''
          let logtype = ''
          let span = '-'
          let codepos = ''
          let msg = ''
          if (['[Debug]', '[Info]', '[Warn]', '[Error]'].includes(parts1[1])) {
            time = time_pre + parts1[0]
            logtype = parts1[1]
            codepos = parts1[2]
            msg = parts1.slice(3).join(' ')

            if (parts1[3] === 'Stack:') {
              msg += '\n' + lines.slice(i + 1).join('\n')
              i += lines.length - i - 1
            }
          } else if (parts1[1] === '[exec:') {
            time = time_pre + parts1[0]
            logtype = parts1[3]
            span = /(\d+)\]/g.exec(parts1[2])[1]

            if (logtype === '[HTTP]') {
              const parts2 = line.split(', ')
              if (parts2.length >= 2) {
                const parts3 = parts2[0].split(' ')
                time = time_pre + parts3[0]
                logtype = parts3[3]
                span = /(\d+)\]/g.exec(parts3[2])[1]

                if (parts3.length === 8) {
                  codepos = parts3[7]
                }

                if (parts2.length === 3 && parts3.length === 8) {
                  msg = parts3[4] + ' ' + parts3[5] + '\nMethod: ' + parts3[6] + '\n' + parts2[2]
                } else if (parts2.length === 2 && parts3.length === 8) {
                  msg = parts3[4] + ' ' + parts3[5] + '\nMethod: ' + parts3[6] + '\n' + parts2[1]
                } else {
                  msg = parts1.slice(4).join(' ')
                }
              } else {
                msg = parts1.slice(4).join(' ')
              }
            } else if (['[Redis]', '[MySql]', '[Rpc]'].includes(logtype)) {
              const parts2 = parts1.slice(4).join(' ').split(' -- Call At: ')
              if (parts2.length === 2) {
                msg = parts2[0]
                codepos = parts2[1].split(' , ').join('\n')
              } else {
                msg = parts1.slice(4).join(' ')
              }
            }
          } else if (parts1[1] === '[AsyncFunc]') {
            time = time_pre + parts1[0]
            logtype = parts1[1]
            msg = parts1.slice(2).join(' ')

            const parts2 = parts1.slice(2).join(' ').split(' -- Call At: ')
            if (parts2.length === 2) {
              msg = parts2[0]
              codepos = parts2[1].split(' , ').join('\n')
            }
          }

          this.iodatas.push({
            time,
            logtype,
            span,
            codepos,
            msg
          })

          i++
        }
      }
    },
    detailClose() {
      this.dataFormVisible = false
    },
    copyPart(part) {
      navigator.clipboard.writeText(part).then(() => {
        this.$message.success('复制成功！')
      }).catch(() => {
        this.$message.error('复制失败！')
      })
    }
  }
}
</script>

<style scoped>
/deep/ .el-table .cell {
  white-space: pre-line;/*保留换行符*/
}
</style>
